package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type Place struct {
	ID int `gorm:primary_key`
	Name string
	Town Town
	TownId int `gorm:"ForeignKey:id"` //自动建表不会触发，但是创建数据时是可以关联创建的
}

type Town struct {
	ID int `gorm:"primary_key"`
	Name string
}

type Customer struct {
	CustomerID   int `gorm:"primary_key"`
	CustomerName string
	Contacts     []Contact `gorm:"ForeignKey:CustId"`
}

type Contact struct {
	ContactID   int `gorm:"primary_key"`
	CountryCode int
	MobileNo    uint
	CustId      int
}

type UserL struct {
	gorm.Model
	Uname     string
	Languages []Language `gorm:"many2many:user_languages;"` //多对多要指定一个中间表
}

type Language struct {
	gorm.Model
	Name string
}

type UserLanguages struct {
	UserLId    uint
	LanguageId uint
}

func main() {
	db, err := gorm.Open("mysql", "wenjuhao:123456@tcp(127.0.0.1:3306)/goweb?charset=utf8&parseTime=True")
	if err != nil {
		panic(err)
	}
	defer db.Close()

	//普通的查询，没有关联towns表
	places := Place{}
	db.Debug().Where("name=?", "Shivaji  Nagar").Find(&places)
	fmt.Println("", places)

	//关联查询
	//有关联towns表
	//Town 是关系中的源的字段名
	//要指定model，然后find里传入关联字段的指针
	//关联查询依赖于普通查询，要先使用普通查询查出基础数据然后使用关联查询查询关联的资源
	db.Debug().Model(&places).Association("Town").Find(&places.Town)
	fmt.Println(" Association:", places.Town.Name)

	//belong to
	var town Town
	db.Model(&places).Related(&town)
	fmt.Println("Related: ", places.Town.ID)

	//one2many
	var customers  Customer
	//使用where in 语句时，？要用（）括起来

	//预加载 one2many
	//Contacts 是Customer结构中的关联contact数据的字段
	db.Debug().Model(&Customer{}).Where("customer_name = ?", "Martin").Preload("Contacts").Find(&customers)
	fmt.Println("customers: ", customers)

	//更新数据
	db.Debug().Model(&Contact{}).Where("cust_id = ?", 7).Update("country_code", 77)
	//级联删除
	//where里使用结构体当做字段，要用model的结构的指针，例如这里的&Customer，而不是代码里自定义的承接结果的结构
	//设置了级联删除，不可以直接用数据库工具操作被关联的表执行删除
	//db.Debug().Where(&Customer{CustomerName:customers.CustomerName}).Delete(&customers)
	//fmt.Println("delete: ", customers)

	//many2many
	user := &UserL{}
	db.Debug().Where(&UserL{Uname:"Ray"}).Find(&user)
	fmt.Println(user)

	//关联查询依赖于基础查询，要先查询基础数据，然后在此基础上执行关联查询
	err = db.Debug().Model(&user).Association("Languages").Find(&user.Languages).Error
	fmt.Println("User is now comming", user, err)
}